package com.itcoon.cloud.framework.webmvc.trace;

import com.itcoon.cloud.framework.webmvc.config.properties.GlobalWebConfigProperties;
import com.itcoon.cloud.framework.webmvc.trace.enums.LogSegment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class HttpTraceLogger implements TraceLogResolver {

    public static final Logger log = LoggerFactory.getLogger(HttpTraceLogger.class);

    private final GlobalWebConfigProperties.HttpTrace httpTrace;

    public HttpTraceLogger(GlobalWebConfigProperties.HttpTrace httpTrace) {
        this.httpTrace = httpTrace;
    }

    @Override
    public void resolve(HttpTraceLog traceLog) {
        List<LogSegment> segments = httpTrace.getSegments();
        StringJoiner joiner = new StringJoiner(",");
        List<Object> arguments = new ArrayList<>();
        for (LogSegment segment : segments) {
            if (segment == LogSegment.METHOD) {
                joiner.add("method={}");
                arguments.add(traceLog.getMethod());
            } else if (segment == LogSegment.URI) {
                joiner.add("uri={}");
                arguments.add(traceLog.getPath());
            } else if (segment == LogSegment.PARAMETER && traceLog.getParameterMap() != null) {
                joiner.add("parameter={}");
                StringJoiner parameterJoiner = new StringJoiner(",");
                for (Map.Entry<String, String[]> entry : traceLog.getParameterMap().entrySet()) {
                    parameterJoiner.add("{" + entry.getKey() + ":" + Arrays.toString(entry.getValue()) + "}");
                }
                arguments.add("[" + parameterJoiner + "]");
            } else if (segment == LogSegment.REQUEST_BODY && traceLog.getRequestBody() != null) {
                joiner.add("requestBody={}");
                arguments.add(traceLog.getRequestBody());
            } else if (segment == LogSegment.RESPONSE_BODY && traceLog.getResponseBody() != null) {
                joiner.add("responseBody={}");
                arguments.add(traceLog.getResponseBody());
            } else if (segment == LogSegment.REQUEST_HEADER && traceLog.getRequestHeaderMap() != null) {
                joiner.add("header={}");
                arguments.add(traceLog.getRequestHeaderMap());
            } else if (segment == LogSegment.RESPONSE_HEADER && traceLog.getResponseHeaderMap() != null) {
                joiner.add("header={}");
                arguments.add(traceLog.getResponseHeaderMap());
            } else if (segment == LogSegment.DURATION) {
                joiner.add("timeTaken={}");
                arguments.add(traceLog.getTimeTaken());
            } else if (segment == LogSegment.USER_IP && traceLog.getUserIp() != null) {
                joiner.add("userIp={}");
                arguments.add(traceLog.getUserIp());
            } else if (segment == LogSegment.STATUS) {
                joiner.add("status={}");
                arguments.add(traceLog.getStatus());
            }
        }
        log.info("Http trace log: " + joiner, arguments.toArray());
    }
}
